#! /usr/bin/env python

## @package drawtracker
# Package for drawing tracker elements.
# @version 1.0
#
# Usage: %prog
# Produces a labelled single tracker layer.
#
# @todo Make configurable with command line options.
# @todo Make the minimum thickness replacement universal.


import os
import tempfile
import shutil
from math import *

## Writes the header of a pspicture LaTeX document.
#
def writeheader():
    out = ""
    out += "\\documentclass{article}\n"
    out += "\\usepackage{pstricks}\n"
    out += "\\usepackage{pst-all}\n"
    out += "\\selectcolormodel{rgb}\n"
#%%\usepackage{amsmath}
#%%\usepackage{amssymb}
#%%\usepackage{relsize}
    out += "\\usepackage{pspicture}\n"
    out += "\\usepackage[dvips,paperwidth=5cm,paperheight=4cm,left=0cm,right=0cm,top=0cm,bottom=0cm,headheight=0pt,headsep=0pt,footskip=0pt,\n"
#%		out += ('  left=%4.3fcm, right=0cm,\n' %(inputdata.description['LeftMargin']-0.45,))
#%		out += ('  top=%4.3fcm,  bottom=0cm,\n' %(inputdata.description['TopMargin']-0.30,))
#%		out += ('  paperwidth=%scm,paperheight=%scm\n' %(papersizex,papersizey))
    out += "]{geometry}\n"
    out += "\\oddsidemargin=-1in\n"
    out += "\\topmargin=-1in\n"
    out += "\\parindent=0pt\n"
    out += "\\begin{document}\n"
    out += "\\pagestyle{empty}\n"
    out += "\\SpecialCoor\n"
    out += "\\setlength{\unitlength}{1.0cm}\n"
    out += "\\begin{pspicture}(0,0)(-2.0,2.0)\n"
    out += "\\linethickness{0.8pt}\n"
    return out 

## Writes the footer for a pspicture LaTeX file.
#
def writefooter():
    out = ""
    out += "\\end{pspicture}\n"
    out += "\\end{document}\n"
    return out

## Draws a segment of a radial tracker layer.
# @param x The x position of the tracker layer centre.
# @param y The y position of the tracker layer centre.
# @param phi1 The starting azimuthal angle of the segment (degrees).
# @param phi2 The ending azimuthal angle of the segment (degrees).
# @param rho1 The inner radius of the segment.
# @param rho2 The outer radius of the segment.
# @param onoroff Whether the segment is on (hit) or off (unhit).
#
def drawsegment(x, y, phi1, phi2, rho1, rho2, onoroff):
    out = ""
    out += "\\pscustom[linewidth=0.3pt,linecolor=black]{\n"
    out += "\\psarc(%5.2f,%5.2f){%5.2f}{%5.2f}{%5.2f}\n" % (x,y,rho1,phi1,phi2)
    out += "\\psarcn(%5.2f,%5.2f){%5.2f}{%5.2f}{%5.2f}\n" % (x,y,rho2,phi2,phi1)
    out += "\\closepath\n"
    out += "}\n"
    if (onoroff):
        out += "\\pscustom*[linecolor=red]{\n"
        out += "\\psarc(%5.2f,%5.2f){%5.2f}{%5.2f}{%5.2f}\n" % (x,y,rho1,phi1,phi2)
        out += "\\psarcn(%5.2f,%5.2f){%5.2f}{%5.2f}{%5.2f}\n" % (x,y,rho2,phi2,phi1)
        out += "\\closepath\n"
        out += "}\n"
    return out

## Draws a label to display the radius and thickness of a radial tracker layer.
# @param radius The radius of the tracker.
# @param thickness The thickness of the tracker. Can be zero.
def drawtrackerradius(radius,thickness):
    barwidth = 0.1
    x1 = radius + 0.3
    y1 = 0.0
    y2 = radius
    y3 = y2 + thickness
    # if the user supplies a very small thickness, replace with the minimum
    # @todo Make the universal thickness configurable.
    drawthickness = thickness
    if (thickness < 0.001):
        y3 = y2 + 0.05
        drawthickness = 0.05
    out = ''
    # the radius arrow
    out += '\\psline[linewidth=0.3pt]{<->}(%5.2f,%5.2f)(%5.2f,%5.2f)\n' % (x1,y1,x1,y2)
    # the lower radius bar
    out += '\\psline[linewidth=0.3pt](%5.2f,%5.2f)(%5.2f,%5.2f)\n' % (x1-barwidth,y1,x1+barwidth,y1)
    # the upper radius bar
    out += '\\psline[linewidth=0.3pt](%5.2f,%5.2f)(%5.2f,%5.2f)\n' % (x1-barwidth,y2,x1+barwidth,y2)
    # the thickness bar
    out += '\\psline[linewidth=0.3pt](%5.2f,%5.2f)(%5.2f,%5.2f)\n' % (x1-barwidth,y3,x1+barwidth,y3)
    # the thickness upper arrow
    out += '\\psline[linewidth=0.3pt]{<-}(%5.2f,%5.2f)(%5.2f,%5.2f)\n' % (x1,y3,x1,y3+0.2)
    # the rho_det label
    out += '\\uput{0.14}[0](%5.2f,%5.2f){\\scriptsize $\\rho_{\\mathrm{det.}}$}\n' % (x1,radius/2.)
    # the Delta_rho label
    out += '\\uput{0.14}[0](%5.2f,%5.2f){\\scriptsize $\\Delta \\rho_{\\mathrm{det.}}$}\n' % (x1,radius+drawthickness)
    
    return out

## Draws a radial tracker segment label.
# @param phi1 The anti-clockwise-most angle (degrees) to label.
# @param phi2 The clockwise-most angle (degrees) to label.
# @param radius The radial distance at which to place the labelling arrow.
#
def drawradlabel(phi1,phi2,radius):
    out = ''
    # azimuthal arrow
    out += '\\psarc[linewidth=0.3pt]{<->}(0.0,0.0){%5.2f}{%5.2f}{%5.2f}\n' % (radius,phi1,phi2)
    # arrow bars
    out += '\\psline[linewidth=0.3pt](%5.2f;%5.2f)(%5.2f;%5.2f)' % (radius-0.1,phi1,radius+0.1,phi1)
    out += '\\psline[linewidth=0.3pt](%5.2f;%5.2f)(%5.2f;%5.2f)' % (radius-0.1,phi2,radius+0.1,phi2)
    # label text
    phiav = (phi1 + phi2)/2.
    out += '\\uput{0.3}[%5.2f](%5.2f;%5.2f){\\scriptsize $\\Delta \\phi_{\\mathrm{det.}}$}\n' % (phiav+180., radius, phiav)
    # = \\frac{2 \\pi}{N^{\\phi}_{\\mathrm{det.}}}
    return out

## Base names of the files produced by the script.
filename = 'fig1'
#texfilename = filename + '.tex'

## Current working directory.
cwd = os.getcwd()
## Temporary directory for files used in figure construction.
tempdir = tempfile.mkdtemp('.draw-tracker')
## Path to the .tex file.
texpath = os.path.join(tempdir, filename+'.tex')

## The Tex file to which the figure is written.
texfile = open(texpath,'w')

# Write the LaTeX document header.
texfile.write(writeheader())

## The radius of the tracker layer to draw, \f$\rho_{\mathrm{det.}}\f$
rho_det = 1.5
## The thickness of the tracker layer to draw, \f$\Delta \rho_{\mathrm{det.}}\f$.
Delta_rho = 0.0
## The number of azimuthal segments, \f$N^{\phi}_{\mathrm{det.}}\f$.
N_det = 32

# Draw N_det segments to make up the tracker.
for i in range(N_det):
    ## Azimuthal angle 1 in the ith segment.
    phi1 = i * (360. / N_det)
    ## Azimuthal angle 2 in the ith segment.
    phi2 = phi1 + (360. / N_det)
    # Draw the segment with the user thickness of minimum thickness if Delta_rho is too small.
    if (Delta_rho < 0.001):
        texfile.write(drawsegment(0.,0.,phi1,phi2,rho_det,rho_det+0.05,False))
    else:
        texfile.write(drawsegment(0.,0.,phi1,phi2,rho_det,rho_det+Delta_rho,False))

# draw the rhodet arrow
texfile.write(drawtrackerradius(rho_det,Delta_rho))
texfile.write(drawradlabel(7.*(360./N_det),8.*(360./N_det),rho_det-0.2))

# Write the LaTeX document footer.
texfile.write(writefooter())
# Close the LaTeX file.
texfile.close()


#Make the PDF from the latex.
import subprocess

#run LaTeX on the generated figure LaTeX file.
#print texpath
#texcmd = ["latex", texpath]

## Process for running the LaTeX figure generation.
texproc = subprocess.Popen(["latex", texpath], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=tempdir)
texproc.wait()

## Process for running the dvi to ps conversion.
dvproc = subprocess.Popen(["dvips", os.path.join(tempdir,filename+".dvi")], stdout=subprocess.PIPE, cwd=tempdir)
dvproc.wait()

## Process for running the ps to pdf conversion.
cnvproc = subprocess.Popen(["ps2pdf", os.path.join(tempdir,filename+".ps")], stdout=subprocess.PIPE, cwd=tempdir)
cnvproc.wait()

## The output path for the final PDF.
outpath = os.path.join(tempdir, filename+".pdf")
if os.path.exists(outpath):
    shutil.copy(outpath, cwd)
## The output path for the final .tex file (for debugging).
outtex = os.path.join(tempdir, filename+".tex")
if os.path.exists(outtex):
    shutil.copy(outtex, cwd)

shutil.rmtree(tempdir, ignore_errors=True) # delete the temporary files
